/*
 * Created on 2008-3-7
 *
 * TODO
 */
package jacky.lanlan.song.extension.struts.interceptor;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.Map;

import jacky.lanlan.song.closure.Factory;
import jacky.lanlan.song.extension.struts.InfrastructureKeys;
import jacky.lanlan.song.extension.struts.action.ValueStack;
import jacky.lanlan.song.extension.struts.annotation.Forward;
import jacky.lanlan.song.extension.struts.annotation.JSON;
import jacky.lanlan.song.extension.struts.annotation.JSON.JSONEncoder;
import jacky.lanlan.song.io.IOUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 处理方法远程调用的拦截器。优先级400。
 * 
 * @author Jacky.Song
 */
public class JSONEncodeInterceptor extends ActionInterceptorAdapter {

	@Override
	@SuppressWarnings("unchecked")
	public String preHandle(HttpServletRequest request,
			HttpServletResponse response, Object action) throws Exception {
		Method method=(Method)request.getAttribute(InfrastructureKeys.EXECUTION);
		
		if (method.isAnnotationPresent(JSON.class)) { // 如果是Remote方法
			ValueStack vs=(ValueStack)request.getAttribute(InfrastructureKeys.VSAC);
			Map<String,String> reqData = (Map)request.getAttribute(InfrastructureKeys.REQ_DATA);
			// 通过反射调用方法
			Object reValue = method.invoke(action, new Object[] {vs, reqData});
			this.encodeAndResponse(reValue, method, response); // 编码返回值为JSON格式，然后发送给请求方
			return Forward.INPUT;
		}
		
		return null; // 其他方法不管
	}

	// 编码为JSON并响应
	private void encodeAndResponse(Object reValue, Method execution,
			HttpServletResponse response)
			throws Exception {
		
		String json = createJSONEncoder(execution).encode(reValue, execution);
		try {
			OutputStream os = response.getOutputStream();
			IOUtils.write(json, os);
			os.flush();
		}
		catch (IOException e) {
		}
	}

	// 每个执行方法可以有不同的JSON编码器
	private JSONEncoder createJSONEncoder(Method execution) {
		Factory<JSONEncoder> factory = null;
		JSONEncoder encoder = null;
		try {
			factory = execution.getAnnotation(JSON.class)
					.encoder().newInstance();
			encoder = factory.create();
		}
		catch (Exception e) {
			throw new RuntimeException("不能创建JSONEncoder：" + e);
		}
		return encoder;
	}
	
	public int priority() {
		return 400;
	}
	
}
